﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Microsoft.Ajax.Utilities;
using CodeExp = System.Linq.Expressions.Expression;

namespace JsConverter
{

	public class Js
	{


		public void Convert( string source )
		{
			JSParser parser = new JSParser( source );

			var content = 
				parser.Parse(
					new CodeSettings()
					{
						BlocksStartOnSameLine = BlockStart.UseSource,
						EvalLiteralExpressions = true,
						LocalRenaming = LocalRenaming.KeepAll,
						MinifyCode = false,
						OutputMode = OutputMode.MultipleLines,
						PreserveFunctionNames = true,
						RemoveFunctionExpressionNames = true,
						ReorderScopeDeclarations = true,
						StrictMode = true,
						StripDebugStatements = false
					} );


			JsToExpressionMapper mapper = new JsToExpressionMapper();

			content.Accept( mapper );
		}


	}


	public class JsToExpressionMapper : TreeVisitor
	{
//		private Stack<System.Linq.Expressions.Expression> blocks = new Stack<System.Linq.Expressions.Expression>();
		private Stack<System.Linq.Expressions.Expression> statements = new Stack<System.Linq.Expressions.Expression>();

		public System.Linq.Expressions.Expression Exp
		{
			get;
			private set;
		}

		//protected void PushBlock( System.Linq.Expressions.Expression block )
		//{
		//    this.AppendStatement( block );
		//    this.blocks.Push( block );
		//}

		//protected void AppendStatement( System.Linq.Expressions.Expression statement )
		//{
		//    var block = this.blocks.Peek();

		//}

		protected void PushStatement( System.Linq.Expressions.Expression statement )
		{
			this.statements.Push( statement );
		}

		protected IEnumerable<CodeExp> PopStatements()
		{

			return null;
		}

		public override void Visit( ArrayLiteral node )
		{
			base.Visit( node );
		}

		public override void Visit( FunctionObject node )
		{
			base.Visit( node );
		}

		public override void Visit( ReturnNode node )
		{
			base.Visit( node );

			var statement = this.PopStatements().First();

			this.PushStatement( CodeExp.Return( CodeExp.Label(), statement ) );
		}

		public override void Visit( BinaryOperator node )
		{
			base.Visit( node );
		}

		public override void Visit( AstNodeList node )
		{
			base.Visit( node );
		}

		public override void Visit( ConstantWrapperPP node )
		{
			base.Visit( node );
		}

		public override void Visit( ConstantWrapper node )
		{
			base.Visit( node );

			this.PushStatement( CodeExp.Constant( Convert.ToInt32( node.Value ) ) );
		}

		public override void Visit( ConstStatement node )
		{
			base.Visit( node );
		}

		public override void Visit( Block node )
		{
			base.Visit( node );
			// CodeExp.SymbolDocument( "" );

			this.PushStatement( CodeExp.Block( this.PopStatements().Block() ) );
		}
	}


	public static class ExpStackExpressions
	{
		

		public static IEnumerable<CodeExp> Block( this IEnumerable<CodeExp> statements )
		{
			return statements.TakeWhile( code => !( code is BlockExpression ) );
		}

	}
}
